Skip to content

[experimental] Preserve CommonJS module boundaries - #14982

Draft
irvinebroque wants to merge 4 commits into
mainfrom
experiment/preserve-commonjs-module-registry
Draft

[experimental] Preserve CommonJS module boundaries#14982
irvinebroque wants to merge 4 commits into
mainfrom
experiment/preserve-commonjs-module-registry

Conversation

@irvinebroque

@irvinebroque irvinebroque commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Experimental draft

This PR is a prototype for review. It is not intended to merge.

Baseline reproduction: https://github.com/irvinebroque/canvaskit-module-registry-repro/

What changes for developers

Some npm packages still ship CommonJS. These packages can depend on CommonJS features such as __dirname, __filename, require, module.exports, relative require() calls, and CommonJS cycles.

Workers supports these features when it receives a file as a CommonJS module. Today, Wrangler and the Cloudflare Vite plugin can bundle that file into the Worker's ES module first. The runtime then receives an ES module, so CommonJS-only values such as __dirname are unavailable.

This prototype preserves eligible npm CommonJS files when you enable the new_module_registry compatibility flag. It supports .js and .cjs files in named npm packages when their require() calls use string literals and resolve to CommonJS or JSON. You continue to import the package normally:

import CanvasKitInit from "canvaskit-wasm";

You do not need a package allowlist, custom module rules, or package-specific source changes.

Today With this prototype
Wrangler or Vite can fold a CommonJS dependency into an ES module. Wrangler and Vite keep supported CommonJS files as separate CommonJS modules.
The Workers runtime sees ES module code and does not provide CommonJS-only values. The Workers runtime receives the file as CommonJS and provides its CommonJS context.
Packages such as CanvasKit fail when they access __dirname. CanvasKit gets past its __dirname failure and reaches its separate Wasm-loading path.

Nothing changes unless you enable new_module_registry.

Wrangler

For bundled, module-format Workers, Wrangler now keeps statically reachable npm CommonJS files out of the main ES module. It includes those files as CommonJS modules when you run local development, a dry run, or a deployment.

Default imports continue to work from ES module Worker code. Named imports work when the package exposes them in a form the build can detect. Relative require() calls, required JSON files, and CommonJS cycles retain their CommonJS behavior. Node.js built-ins continue to work when you enable nodejs_compat.

This prototype does not change service-worker-format or no_bundle builds.

Cloudflare Vite plugin

The Vite plugin now preserves the same CommonJS boundaries in each Worker mode:

  • During development, Vite disables dependency discovery and optimization for a Worker environment using the flag. CommonJS reaches the Workers runtime instead of first becoming ES module code.
  • During a production build, Vite emits preserved CommonJS files separately and records their module type in the generated deployment configuration.
  • During preview, Vite starts the Worker with the same module files and types produced by the build.

You use the same application imports in development, preview, and the build output used for deployment.

Scope and current limits

This behavior is experimental and requires new_module_registry.

  • The prototype supports require("package") and require("./file") calls with exactly one string-literal argument.
  • Other calls, such as require(variable), fail the build or development transform with an experimental diagnostic.
  • A CommonJS require() that resolves to an ES module also fails the transform instead of producing an incomplete deployment.
  • The build emits required JSON as CommonJS code so require("./data.json") returns the parsed value.
  • Preserving CanvasKit fixes its CommonJS __dirname failure. CanvasKit still needs a Workers-compatible Wasm loading setup, which is outside this PR.

This behavior requires no workerd changes. The runtime already supplies the expected CommonJS context when tooling identifies a module as CommonJS.

Validation

The validation branch covers a CommonJS package that uses __dirname, __filename, relative require(), JSON, a Node.js built-in, a cycle, and default and named ES module imports.

I ran the harness with the prototype packages after updating two local expectations: required JSON becomes CommonJS code, and CanvasKit reaches a missing-Wasm-file error after __dirname succeeds.

The checks pass for:

  • Wrangler dry-run output
  • Wrangler local development
  • Vite production output and generated CommonJS rules
  • Vite local development
  • Vite preview
  • CanvasKit's __dirname path in Wrangler and Vite local development

Focused test results:

  • 13 shared CommonJS graph tests
  • 30 Wrangler bundling and upload tests
  • 28 Vite output, preview, and module-reference tests
  • Successful @cloudflare/workers-utils and @cloudflare/vite-plugin builds

The harness verifies deployable Wrangler and Vite build artifacts, but it does not perform a remote deployment.

Wrangler's runtime build also succeeds. In this checkout, unrelated implicit-any errors in ProxyController.ts still block Wrangler declaration generation.

@changeset-bot

changeset-bot Bot commented Aug 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 37557d9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@cloudflare/vite-plugin Minor
@cloudflare/workers-utils Minor
wrangler Minor
@cloudflare/autoconfig Patch
@cloudflare/cli-shared-helpers Patch
@cloudflare/deploy-helpers Patch
@cloudflare/remote-bindings Patch
@cloudflare/vitest-pool-workers Patch
@cloudflare/workers-auth Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ask-bonk

ask-bonk Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

UnknownError: ProviderInitError

github run

@ask-bonk

ask-bonk Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

@irvinebroque Bonk workflow failed. Check the logs for details.

View workflow run · To retry, trigger Bonk again.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

✅ All changesets look good

@pkg-pr-new

pkg-pr-new Bot commented Aug 2, 2026

Copy link
Copy Markdown
@cloudflare/autoconfig

npm i https://pkg.pr.new/@cloudflare/autoconfig@14982

@cloudflare/build-output-utils

npm i https://pkg.pr.new/@cloudflare/build-output-utils@14982

@cloudflare/config

npm i https://pkg.pr.new/@cloudflare/config@14982

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@14982

@cloudflare/deploy-helpers

npm i https://pkg.pr.new/@cloudflare/deploy-helpers@14982

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@14982

miniflare

npm i https://pkg.pr.new/miniflare@14982

@cloudflare/pages-functions

npm i https://pkg.pr.new/@cloudflare/pages-functions@14982

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@14982

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@14982

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@14982

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@14982

@cloudflare/workers-auth

npm i https://pkg.pr.new/@cloudflare/workers-auth@14982

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@14982

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@14982

wrangler

npm i https://pkg.pr.new/wrangler@14982

commit: 37557d9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

2 participants